home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
threads
/
ThreadsTime.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-03
|
7KB
|
223 lines
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA
endcopyright */
/*
* ThreadsTime.c
*
* Demers, April 6, 1990 2:51:18 pm PDT
*/
#include "xr/BasicTypes.h"
#include "xr/Threads.h"
#include "xr/ThreadsBackdoor.h"
#include "xr/ThreadsSignalsPrivate.h"
#include "xr/ThreadsStatsPrivate.h"
/*
* Time since boot
*/
#define XR_TicksFromTimeval(sec,usec) \
(((sec)*XR_TICKS_PER_SECOND) + ((usec)/XR_USECS_PER_TICK))
#define XR_SetTimevalFromTicks(tvp,ticks) (\
((tvp)->tv_sec = (ticks)/XR_TICKS_PER_SECOND), \
((tvp)->tv_usec = ((ticks)%XR_TICKS_PER_SECOND)*XR_USECS_PER_TICK) \
)
#define XR_TIMESLICE 1 /* ticks per timeslice */
#define XR_TICKS_BETWEEN_SET_TIME (1 * XR_TICKS_PER_SECOND)
XR_Ticks XR_ticksPerSecond = XR_TICKS_PER_SECOND;
unsigned XR_msecsPerTick = XR_MSECS_PER_TICK;
unsigned XR_usecPerTick = XR_USECS_PER_TICK;
XR_Ticks XR_waitForever = XR_WAIT_FOREVER;
XR_Ticks XR_endOfTime = XR_END_OF_TIME;
void
XR_SetBootTime ()
/*
Initialize boot time for later use.
Called once before alarm int handler is initialized.
*/
{
if( gettimeofday(&(XR_sysArea->sa_bootTime), NIL) != 0 )
XR_Panic("SetBootTime");
XR_InitPSL(&(XR_sysArea->sa_ticksSinceBootLock));
XR_sysArea->sa_bootTime.tv_usec = 0;
XR_sysArea->sa_ticksSinceBoot = 0;
XR_sysArea->sa_ticksSinceBootDeficit = 0;
}
void
XR_SetTime()
{
struct timeval tv;
XR_Ticks newTicksSinceBoot;
int deltaTicks;
if( gettimeofday(&tv, NIL) != 0 ) XR_Panic("SetTime");
newTicksSinceBoot = XR_TicksFromTimeval(
tv.tv_sec-XR_sysArea->sa_bootTime.tv_sec,
tv.tv_usec
);
deltaTicks = ((int)(newTicksSinceBoot - XR_sysArea->sa_ticksSinceBoot));
if (deltaTicks < 0) {
XR_sysArea->sa_ticksSinceBootDeficit = -XR_sysArea->sa_numVP;
/* In this case, we interpret it as a count of alarm signals */
/* to ignore for updating tick count, not a real deficit. */
/* We assume we never get ahead by much, so we will eventually */
/* synchronize, in spite of the sloppiness here. */
} else {
XR_sysArea->sa_ticksSinceBootDeficit = deltaTicks;
}
}
XR_Ticks
XR_TicksSinceBoot()
/*
Return number of ticks since PCR was started.
*/
{
return( XR_sysArea->sa_ticksSinceBoot );
}
/*
* Alarm signals
*/
void
XR_AlarmSigHandler (sig, code, scp, addr)
int sig;
int code;
struct sigcontext *scp;
XR_Pointer addr;
{
static int ticksUntilSetTime = 0;
XR_Ticks pvtTicksSinceBoot;
XR_Ticks deficitAdjustment;
if( scp->sc_onstack ) XR_Panic("AlarmSigHandler 0");
if( XR_vpe == NIL ) return;
if( XR_currThread == NIL ) /* can happen during startup */ return;
XR_LockErrno();
pvtTicksSinceBoot = XR_vpe->vpe_ticksSinceBoot + XR_TIMESLICE;
if (XR_sysArea->sa_ticksSinceBootDeficit > 0) {
deficitAdjustment =
XR_sysArea->sa_ticksSinceBootDeficit/XR_TICKS_BETWEEN_SET_TIME
+ 1;
} else if (XR_sysArea->sa_ticksSinceBootDeficit < 0) {
/* We should lose this tick in all vp's. */
deficitAdjustment = -1;
XR_sysArea->sa_ticksSinceBootDeficit++;
} else {
deficitAdjustment = 0;
/* We son't try to adjust a fast clock. That shouldn't happen */
/* anyway. If it does, we'll eventually lose enough ticks to */
/* make up for it. */
}
pvtTicksSinceBoot += deficitAdjustment;
XR_vpe->vpe_ticksSinceBoot = pvtTicksSinceBoot;
if( !XR_TestAndSet(&(XR_sysArea->sa_ticksSinceBootLock)) ) {
/*
* Got the lock, update the clock and release the lock ...
*/
# if XR_STATS
XR_sysArea->sa_stats[XR_STATS_HndAlarm] += 1;
XR_sysArea->sa_stats[XR_STATS_WhenHndAlarm] =
XR_sysArea->sa_stats[XR_STATS_Switch];
# endif /* XR_STATS */
if( pvtTicksSinceBoot <= XR_sysArea->sa_ticksSinceBoot ) {
XR_vpe->vpe_ticksSinceBoot = XR_sysArea->sa_ticksSinceBoot;
} else {
/* update XR_sysArea->sa_ticksSinceBoot using deficit */
if( (ticksUntilSetTime -= XR_TIMESLICE) < 0 ) {
XR_SetTime();
ticksUntilSetTime = XR_TICKS_BETWEEN_SET_TIME;
} else {
XR_sysArea->sa_ticksSinceBoot = pvtTicksSinceBoot;
XR_sysArea->sa_ticksSinceBootDeficit -= deficitAdjustment;
}
if( XR_TryMeta( /*whence = */ "AlarmSigHandler" ) ) {
/*
* We now hold the metalock.
*/
XR_sysArea->sa_doTimeouts = XR_DoTimeouts();
XR_UnlockMeta();
} else {
/*
* Somebody holds the metalock. It might be this
* processor, so we can't spin waiting for it
* to be released.
* Just set XR_sysArea->sa_doTimeouts and let the
* next call to Switch do the work.
*/
XR_sysArea->sa_doTimeouts = TRUE;
}
}
XR_Unset(&(XR_sysArea->sa_ticksSinceBootLock));
} else {
/*
* Another VP holds the lock, defer to it ...
*/
XR_vpe->vpe_ticksSinceBoot = (
(pvtTicksSinceBoot < XR_sysArea->sa_ticksSinceBoot)
? XR_sysArea->sa_ticksSinceBoot
: pvtTicksSinceBoot
);
}
{
extern XR_VPE XR_SlowVP();
register XR_VPE vp = XR_SlowVP();
if (vp != NIL && vp != XR_vpe) {
XR_RequestResched(vp);
}
}
XR_RequestResched( XR_vpe );
XR_UnlockErrno();
}
void
XR_AlarmSigHandlerInit (installed)
bool installed;
/*
Arrange for periodic SIGALRM interrupts on VPs but not IOPs.
KLUDGE: the first interrupt doesn't occur for a while,
to give thread initialization time to complete.
Called independently on each processor (not just VPs).
*/
{
if( (XR_vpe != NIL) && installed ) {
struct itimerval itv;
XR_SetTimevalFromTicks(&(itv.it_interval), XR_TIMESLICE);
XR_SetTimevalFromTicks(&(itv.it_value), 2*XR_TICKS_PER_SECOND);
if( setitimer(ITIMER_REAL, &itv, NIL) != 0 )
XR_Panic("AlarmSigHandlerInit 0");
}
}